package com.c6906.vdam.das.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.c6906.vdam.das.common.DateUtils;
import com.c6906.vdam.das.config.DasOpenStatus;
import com.c6906.vdam.das.config.redis.RedisUtils;
import com.c6906.vdam.das.dao.TerminalBusinessInfoDAO;
import com.c6906.vdam.das.model.entity.TerminalBusinessInfo;
import com.c6906.vdam.das.model.entity.TerminalData;
import com.c6906.vdam.das.model.entity.VehiclesLast;
import com.c6906.vdam.das.service.TerminalBusinessInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Author : TAOHUIQI @Date: 2024/6/15 20:51 @Description:
 */
@Service
@EnableConfigurationProperties({DasOpenStatus.class})
public class TerminalBusinessInfoServiceImpl implements TerminalBusinessInfoService {

    private static final Logger logger = LoggerFactory.getLogger(TerminalBusinessInfoServiceImpl.class);
    private static final String PRE_REDIS_KEY = "SN";
    private static final String PRE_GPS_DATA_REDIS_KEY = "GPS_DATA";
    @Resource
    RedisUtils redisUtils;
    @Resource
    DasOpenStatus dasOpenStatus;
    @Resource
    private TerminalBusinessInfoDAO terminalBusinessInfoDAO;

    @Override
    public boolean updateBatchTerminalDataToDM() {
        int startRow = 0;
        int offset = 1000;
        List<VehiclesLast> list;
        List<VehiclesLast> updateList = new ArrayList<>();
        while (true) {
            list = terminalBusinessInfoDAO.getVehiclesLastMapInfoList(startRow, offset);
            LocalDateTime time1 = LocalDateTime.now();
            if (!CollectionUtils.isEmpty(list)) {
                // 根据设备编号从redis中取最新终端轨迹数据和终端最后心跳时间
                for (VehiclesLast vehiclesLast : list) {
                    VehiclesLast vehiclesLastRedis = this.redisUtils
                            .getOneTerminalStatuses(vehiclesLast.getTerminalSn());
                    if (null != vehiclesLastRedis) {
                        // 根据终端号，获取终端最后心跳时间
                        if (!ObjectUtils.isEmpty(vehiclesLastRedis.getStrLastHeartbeatTime())) {
                            // 判断更新终端状态和最后心跳时间
                            setTerminalLastHeartbeatTimeAndStatus(vehiclesLastRedis.getStrLastHeartbeatTime(),
                                    vehiclesLastRedis);
                        }
                        // 添加到入库List
                        updateList.add(vehiclesLastRedis);
                    }
                }
                // 清空原list
                list.clear();
                // 更新轨迹表
                LocalDateTime time4 = LocalDateTime.now();
                if (!updateList.isEmpty()) {
                    terminalBusinessInfoDAO.updateBatchByTerminalSn(updateList);
                }
                LocalDateTime time5 = LocalDateTime.now();
                logger.debug("time1:{},time4:{},time5:{}", time1, time4, time5);
                // 清空最新轨迹List
                updateList.clear();
                // 查询下一批
                startRow = startRow + offset;
            } else {
                logger.info("所有终端设备最新轨迹数据更新到DM完成, startRow:{}", startRow);
                break;
            }
        }
        return true;
    }

    @Override
    public String initRedisForList(List<String> snList) {
        List<TerminalBusinessInfo> list = terminalBusinessInfoDAO.getTerminalBusinessBySNList(snList);
        try {
            if (!CollectionUtils.isEmpty(list)) {
                for (TerminalBusinessInfo info : list) {
                    this.redisUtils.set(PRE_REDIS_KEY + info.getTerminalSn(), JSON.toJSONString(info));
                    logger.info("initRedisForSingle设备编号为: " + PRE_REDIS_KEY + "{}", info.getTerminalSn());
                }
                return "SUCCESS";
            }
        } catch (Exception e) {
            logger.error("initRedisForSingle", e);
            return "FAIL";
        }
        return "FAIL";
    }

    @Override
    public List<VehiclesLast> getVehiclesLastMapInfoList(int pageSize, int pageNum) {
        return terminalBusinessInfoDAO.getVehiclesLastMapInfoList(pageSize, pageNum);
    }

    @Override
    public List<TerminalBusinessInfo> queryTerminalBusinessBySNToRedis(String sn) {
        List<TerminalBusinessInfo> list = terminalBusinessInfoDAO.getTerminalBusinessBySN(sn);
        if (!CollectionUtils.isEmpty(list)) {
            for (TerminalBusinessInfo info : list) {
                this.redisUtils.set(PRE_REDIS_KEY + info.getTerminalSn(), JSON.toJSONString(info));
                logger.info("设备编号为: " + PRE_REDIS_KEY + "{}", info.getTerminalSn());
            }
        } else {
            logger.info("设备编号不存在");
        }
        return list;
    }

    @Override
    public TerminalBusinessInfo getTerminalBySNFromRedis(String sn) {
        String info = (String) this.redisUtils.get(PRE_REDIS_KEY + sn);
        // JSONString转为对象
        return JSON.parseObject(info, TerminalBusinessInfo.class);
    }

    @Override
    public boolean terminalIsExistFormRedis(String sn) {
        String info = (String) this.redisUtils.get(PRE_REDIS_KEY + sn);
        if (!ObjectUtils.isEmpty(info)) {
            // JSONString转为对象
            TerminalBusinessInfo terminalBusinessInfo = JSON.parseObject(info, TerminalBusinessInfo.class);
            return null != terminalBusinessInfo;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBatchByTerminalSn(List<TerminalData> list) {
        try {
            if (!CollectionUtils.isEmpty(list)) {
                List<VehiclesLast> vehiclesLastList = new ArrayList<>();
                for (TerminalData terminalData : list) {
                    VehiclesLast vehiclesLast = new VehiclesLast();
                    vehiclesLast.setTerminalSn(terminalData.getTerminalSn());
                    vehiclesLast.setAccStatusId(terminalData.getTerminalAccStatus());
                    vehiclesLast.setLocationMark(terminalData.getIsFixed());
                    vehiclesLast.setLongitude(DateUtils.strToDouble(terminalData.getLongitude()));
                    vehiclesLast.setLatitude(DateUtils.strToDouble(terminalData.getLatitude()));
                    vehiclesLast.setElevation(terminalData.getElevation());
                    vehiclesLast.setDirection(terminalData.getDirection());
                    vehiclesLast.setTerminalTime(DateUtils.strToDate(terminalData.getTerminalTime()));
                    vehiclesLast.setLocationTime(DateUtils.strToDate(terminalData.getTerminalTime()));
                    vehiclesLast.setTerminalMiles(DateUtils.strToDouble(terminalData.getTerminalMiles()));
                    vehiclesLast.setTodayMiles(DateUtils.strToDouble(terminalData.getTerminalMilesAday()));
                    vehiclesLast.setSpeed(DateUtils.strToDouble(terminalData.getSpeed()));
                    vehiclesLast.setGnssModuleError(DateUtils.strToInt(terminalData.getTerminalGnssError()));
                    vehiclesLast.setGnssError(DateUtils.strToInt(terminalData.getTerminalAntOpen()));
                    vehiclesLast.setGnssShort(DateUtils.strToInt(terminalData.getTerminalAntShort()));
                    vehiclesLast.setOverSpeed(DateUtils.strToInt(terminalData.getTerminalOverSpeed()));
                    vehiclesLast.setPowerDown(DateUtils.strToInt(terminalData.getTerminalNoVol()));
                    vehiclesLast.setUpdateTime(new Date());
                    vehiclesLastList.add(vehiclesLast);
                }
                terminalBusinessInfoDAO.updateBatchByTerminalSn(vehiclesLastList);
                // logger.info("批量更新终端最新轨迹记录成功");
            }
            return true;
        } catch (Exception e) {
            logger.error("执行updateBatchByTerminalSn异常", e);
            return false;
        }
    }

    @Override
    public void saveTerminalDataToRedis(List<TerminalData> list) {
        try {
            if (!CollectionUtils.isEmpty(list)) {
                for (TerminalData terminalData : list) {
                    VehiclesLast vehiclesLast = new VehiclesLast();
                    vehiclesLast.setTerminalSn(terminalData.getTerminalSn());
                    vehiclesLast.setAccStatusId(terminalData.getTerminalAccStatus());
                    vehiclesLast.setLocationMark(terminalData.getIsFixed());
                    vehiclesLast.setLongitude(DateUtils.strToDouble(terminalData.getLongitude()));
                    vehiclesLast.setLatitude(DateUtils.strToDouble(terminalData.getLatitude()));
                    vehiclesLast.setElevation(terminalData.getElevation());
                    vehiclesLast.setDirection(terminalData.getDirection());
                    vehiclesLast.setTerminalTime(DateUtils.strToDate(terminalData.getTerminalTime()));
                    vehiclesLast.setLocationTime(DateUtils.strToDate(terminalData.getTerminalTime()));
                    vehiclesLast.setTerminalMiles(DateUtils.strToDouble(terminalData.getTerminalMiles()));
                    vehiclesLast.setTodayMiles(DateUtils.strToDouble(terminalData.getTerminalMilesAday()));
                    vehiclesLast.setSpeed(DateUtils.strToDouble(terminalData.getSpeed()));
                    vehiclesLast.setGnssModuleError(DateUtils.strToInt(terminalData.getTerminalGnssError()));
                    vehiclesLast.setGnssError(DateUtils.strToInt(terminalData.getTerminalAntOpen()));
                    vehiclesLast.setGnssShort(DateUtils.strToInt(terminalData.getTerminalAntShort()));
                    vehiclesLast.setOverSpeed(DateUtils.strToInt(terminalData.getTerminalOverSpeed()));
                    vehiclesLast.setPowerDown(DateUtils.strToInt(terminalData.getTerminalNoVol()));
                    vehiclesLast.setUpdateTime(new Date());
                    this.redisUtils.set(PRE_GPS_DATA_REDIS_KEY + terminalData.getTerminalSn(),
                            JSON.toJSONString(vehiclesLast));
                }
            }
        } catch (Exception e) {
            logger.error("执行saveTerminalDataToRedis异常", e);
        }
    }

    private void setTerminalLastHeartbeatTimeAndStatus(String lastHeartbeat, VehiclesLast vehiclesLast) {
        // 获取当前时间的毫秒时间戳
        long currentTimeMillis = Instant.now().toEpochMilli();
        // 计算3分钟前的时间戳
        long fiveMinutesAgoMillis = currentTimeMillis - dasOpenStatus.getHeartbeatThresholds();
        long longLastHeartbeat = NumberUtil.parseLong(lastHeartbeat, 0L);
        // 判断是否在线：心跳时间大于等于5分钟前的时间戳即为在线
        boolean isOnline = longLastHeartbeat >= fiveMinutesAgoMillis;
        // logger.info("当前设备在线状态...{}", isOnline);
        if (isOnline) {
            vehiclesLast.setOnlineStatus(1);
            vehiclesLast.setLastHeartbeatTime(new Date(longLastHeartbeat));
        } else {
            // 设置离线状态和最后一次心跳时间
            vehiclesLast.setOnlineStatus(2);
            vehiclesLast.setLastHeartbeatTime(new Date(longLastHeartbeat));
        }
    }
}
